/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - resource
// Copyright( c) 2014.  All Rights Reserved
//
// File:		AEDefaultTextureFormatProvider.h
// Author:		Gianluca Belardelli
// Date:		02/10/2014
//
/////////////////////////////////////////////////////////////////////////
#include <AEEngine.h>
#include "utils/AEStringUtils.h"
#include "internal/lodepng.h"

const char **AEDefaultTextureFormatProvider::GetSupportedFileExtensions( AEINT32 &nListCount )
{
	static const char *lpSupportedFormats[] = {
		"bmp", 
		"png", 
		"jpg", 
		"jpeg", 
		"tga", 
		"pvr", 
		"dds"
	};

	nListCount = AE_ARRAY_SIZE( lpSupportedFormats );

	return lpSupportedFormats;
}

AEUINT32 AEDefaultTextureFormatProvider::CreateTexture( const char *lpFilename, AEINT32 &nFlags )
{
	const char *lpExt = AEStringUtils::GetExtension( lpFilename );
	if( lpExt == 0L )
		return 0;

#ifdef AE_PLATFORM_WIN32
	if( !stricmp( lpExt, "dds" ) )
		_loadDDS( lpFilename );
	else if( !stricmp( lpExt, "png" ) )
		_loadPNG( lpFilename );
	else if( !stricmp( lpExt, "bmp" ) )
		_loadBMP( lpFilename );
#else
	if( !strcasecmp( lpExt, "dds" ) )
		_loadDDS( lpFilename );
	else if( !strcasecmp( lpExt, "png" ) )
		_loadPNG( lpFilename );
	else if( !strcasecmp( lpExt, "bmp" ) )
		_loadBMP( lpFilename );
#endif
	return 1;
}

AETexture *AEDefaultTextureFormatProvider::_loadDDS( const char *lpFileName )
{
	return 0L;
}

AETexture *AEDefaultTextureFormatProvider::_loadPNG( const char *lpFileName )
{
	std::vector<unsigned char> png;
	std::vector<unsigned char> image; //the raw pixels
	unsigned width, height;
	lodepng::State state; //optionally customize this one

	AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( lpFileName );
	if( !lpStream )
		return 0L;

	AEINT32 nSize = lpStream->GetSize();

	AEUINT8 *lpPtr = (AEUINT8*)AEMemoryManager::GetInstancePtr()->GetHeapAllocator().BlockAlloc( nSize );

	lpStream->Read( lpPtr, nSize );
	lpStream->Close();

	//lodepng::load_file(png, lpFileName); //load the image file with given filename
	AEUINT32 uiWidth, uiHeight;
	unsigned error = lodepng_decode32( &m_lpRawBuffer, (unsigned int*)&uiWidth, (unsigned int*)&uiHeight, lpPtr, nSize );
	//lodepng::decode(
	//if there's an error, display it
	if(error)
		printf("decoder error: %d\n%s\n",error,lodepng_error_text(error) );
		
	m_sSizeX = uiWidth;
	m_sSizeY = uiHeight;
	m_cFormat = R8G8B8A8;
	AEMemoryManager::GetInstancePtr()->GetHeapAllocator().BlockFree( lpPtr, nSize );
	//the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...
	//State state contains extra information about the PNG such as text chunks, ...
	return 0L;
}

AETexture *AEDefaultTextureFormatProvider::_loadJPG( const char *lpFileName )
{
	return 0L;
}

AETexture *AEDefaultTextureFormatProvider::_loadTGA( const char *lpFileName )
{
	return 0L;
}

AETexture *AEDefaultTextureFormatProvider::_loadBMP( const char *lpFileName )
{
	AEFileInStreamI *lpStream = AEFileManager::GetInstance()->Open( lpFileName );
	if( !lpStream )
		return 0L;

	AETexture *lpTexture = 0L;

	AEINT32 nSize = lpStream->GetSize();

	AEUINT8 *lpPtr = (AEUINT8*)AEMemoryManager::GetInstancePtr()->GetHeapAllocator().BlockAlloc( nSize );

	lpStream->Read( lpPtr, nSize );
	lpStream->Close();

	AEBMPFileHeader *lpFileHeader = (AEBMPFileHeader *)lpPtr;

	if( lpFileHeader->uiType == AE_BMPMAGIC )
	{
		AEBMPInfoHeader *lpInfoHeader = (AEBMPInfoHeader *)&lpPtr[sizeof(AEBMPFileHeader)];

		m_sSizeX = lpInfoHeader->nWidth;
		m_sSizeY = lpInfoHeader->nHeight;

		if( lpInfoHeader->uiBitCount > 23 && lpInfoHeader->uiCompression == 0 ) // Per ora solo bitmap a 24 o 32 bit senza compressione
		{
			if( lpInfoHeader->uiSize == 0x28 ) // Versione 3
			{
				nSize -= ( sizeof(AEBMPFileHeader) + sizeof(AEBMPInfoHeader) );
				m_lpRawBuffer = (AEUINT8*)AEMemoryManager::GetInstancePtr()->GetHeapAllocator().BlockAlloc( nSize );

				/*int x=0;
				for(int i=nSize; i>-1; i--)
				{
					m_lpRawBuffer[x] = lpPtr[lpFileHeader->uiOffBits+i];
					x++;
				}*/
				memcpy( m_lpRawBuffer, &lpPtr[lpFileHeader->uiOffBits], nSize );

				if( lpInfoHeader->uiBitCount == 24 )
					m_cFormat = B8G8R8;
				else
					m_cFormat = B8G8R8A8;
			}
		}
	}
	
	AEMemoryManager::GetInstancePtr()->GetHeapAllocator().BlockFree( lpPtr, nSize );
	
	return lpTexture;
}

